package com.qiniu.pili.droid.rtcstreaming.demo.activity.streaming;

import android.content.Intent;
import android.hardware.Camera;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.orhanobut.logger.Logger;
import com.qiniu.pili.droid.rtcstreaming.RTCStreamingManager;
import com.qiniu.pili.droid.rtcstreaming.demo.R;
import com.qiniu.pili.droid.rtcstreaming.demo.core.StreamUtils;
import com.qiniu.pili.droid.rtcstreaming.demo.utlis.Constants;
import com.qiniu.pili.droid.rtcstreaming.demo.utlis.ImpDataCollecter;
import com.qiniu.pili.droid.rtcstreaming.demo.utlis.RESFlvData;
import com.qiniu.pili.droid.rtcstreaming.demo.utlis.RESFlvDataCollecter;
import com.qiniu.pili.droid.rtcstreaming.demo.utlis.ScreenRecorder;
import com.qiniu.pili.droid.streaming.AVCodecType;
import com.qiniu.pili.droid.streaming.ScreenStreamingManager;
import com.qiniu.pili.droid.streaming.StreamStatusCallback;
import com.qiniu.pili.droid.streaming.StreamingProfile;
import com.qiniu.pili.droid.streaming.StreamingSessionListener;
import com.qiniu.pili.droid.streaming.StreamingState;
import com.qiniu.pili.droid.streaming.StreamingStateChangedListener;
import com.qiniu.pili.droid.streaming.av.common.PLFourCC;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.net.URISyntaxException;
import java.util.List;

import static com.qiniu.pili.droid.streaming.PLScreenYUVCapturer.REQUEST_CODE;

public class ImportStreamingActivity extends AppCompatActivity implements View.OnClickListener, StreamStatusCallback, StreamingSessionListener, StreamingStateChangedListener {
    private static final String TAG = "leo";
    private MediaProjectionManager mMediaProjectionManager;
    private String pulishString = "rtmp://pili-publish.internal-i-focusing.com/com-i-focusing-live-dev/GID_MARSAR_CLOUD_140154302685827072?e=1514257020&token=0xkNXdzEAVclERzD_DBlZknsmJRdJhVeCuDuKPdI:zaZXqHy-bYB4eCOgJ4pFP3R5hhg=";

    private EditText mEt_rtmp_address;
    private Button mButton;
    private String rtmpAddr;
    private ScreenRecorder mVideoRecorder;
    private boolean isRecording;
    private RTCStreamingManager mStreamingManager;
    private StreamingProfile mStreamingProfile;
    private RESFlvDataCollecter mCollecter;
    private boolean mIsInReadyState = false;


//    private IScreenRecorderAidlInterface recorderAidlInterface;
//    private ServiceConnection connection = new ServiceConnection() {
//        @Override
//        public void onServiceConnected(ComponentName name, IBinder service) {
//            recorderAidlInterface = IScreenRecorderAidlInterface.Stub.asInterface(service);
//        }
//
//        @Override
//        public void onServiceDisconnected(ComponentName name) {
//            recorderAidlInterface = null;
//        }
//    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_import_streaming);
        initView();
        mMediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
        //init SDK
        RTCStreamingManager.init(this);
        //初始化推流对象
        mStreamingManager = new RTCStreamingManager(this, AVCodecType.HW_VIDEO_WITH_HW_AUDIO_CODEC);

//        RTCConferenceOptions options = new RTCConferenceOptions();
//        options.setVideoEncodingSizeRatio(RTCConferenceOptions.VIDEO_ENCODING_SIZE_RATIO.RATIO_16_9);
//        options.setVideoEncodingSizeLevel(RTCConferenceOptions.VIDEO_ENCODING_SIZE_HEIGHT_480);
////        options.setVideoEncodingOrientation(RTCConferenceOptions.VideoEncodingOrientation.PORT);
//// 主播／副主播可以配置不同的连麦码率
//        options.setVideoBitrateRange(300 * 1000, 800 * 1000);
//        mStreamingManager.setConferenceOptions(options);


        mStreamingProfile = new StreamingProfile();
        mStreamingProfile.setVideoQuality(StreamingProfile.VIDEO_QUALITY_MEDIUM2)
                .setAudioQuality(StreamingProfile.AUDIO_QUALITY_MEDIUM1)
                .setEncoderRCMode(StreamingProfile.EncoderRCModes.QUALITY_PRIORITY)
                .setEncodingOrientation(StreamingProfile.ENCODING_ORIENTATION.PORT)
                .setPreferredVideoEncodingSize(768, 480) // 配置推流的尺寸，建议与连麦尺寸一致
                .setYuvFilterMode(StreamingProfile.YuvFilterMode.None)
        ;


        mStreamingManager.prepare(mStreamingProfile);
        mStreamingManager.setStreamStatusCallback(this);
        mStreamingManager.setStreamingSessionListener(this);
        mStreamingManager.setStreamingStateListener(this);

    }

    private void initView() {
        mEt_rtmp_address = (EditText) findViewById(R.id.et_rtmp_address);
        mEt_rtmp_address.setText(Constants.pulishUrl);
        mButton = (Button) findViewById(R.id.button);
        mButton.setOnClickListener(this);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        MediaProjection mediaProjection = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
        }
        if (mediaProjection == null) {
            Log.e("@@", "media projection is null");
            Toast.makeText(this, "media projection is null", Toast.LENGTH_SHORT).show();
            return;
        }

        rtmpAddr = mEt_rtmp_address.getText().toString().trim();
        if (TextUtils.isEmpty(rtmpAddr)) {
            Toast.makeText(this, "rtmp address cannot be null", Toast.LENGTH_SHORT).show();
            return;
        }

//        streamingSender.sendStart(rtmpAddr);
        //                 I420 or NV21 format
//                mStreamingManager.inputVideoFrame(flvData.byteBuffer, RESFlvData.VIDEO_WIDTH, RESFlvData.VIDEO_HEIGHT, 0, false, PLFourCC.FOURCC_I420, RESFlvData.dts);
//                streamingSender.sendFood(flvData, type);


        mCollecter = new RESFlvDataCollecter() {
            @Override
            public void collect(RESFlvData flvData, int type) {

                byte[] byteBuffer = flvData.byteBuffer;
                Logger.d(byteBuffer);
                Logger.e("流数据",byteBuffer);
//                DataHelper.writeFile(flvData.byteBuffer, getsaveDirectory(), "push" + ".txt");
//
////                byte[] byteBuffer = flvData.byteBuffer;
////                int length = byteBuffer.length;
////                Toast.makeText(ImportStreamingActivity.this, String.valueOf(length), Toast.LENGTH_SHORT).show();
//
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        mStreamingManager.startStreaming();
                    }
                }).start();
                mStreamingManager.inputVideoFrame(flvData.byteBuffer, RESFlvData.VIDEO_WIDTH, RESFlvData.VIDEO_HEIGHT, 90, false, PLFourCC.FOURCC_NV21, RESFlvData.dts);


//                 I420 or NV21 format H264
//                streamingSender.sendFood(flvData, type);
//                mStreamingManager.startStreaming();
            }
        };


        mVideoRecorder = new ScreenRecorder(mCollecter, RESFlvData.VIDEO_WIDTH, RESFlvData.VIDEO_HEIGHT, RESFlvData.VIDEO_BITRATE, 1, mediaProjection);
        mVideoRecorder.start();

        mButton.setText("Stop Recorder");
        Toast.makeText(this, "Screen recorder is running...", Toast.LENGTH_SHORT).show();
//        moveTaskToBack(true);
    }

    public static String getsaveDirectory() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            String rootDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "ScreenRecord" + "/";

            File file = new File(rootDir);
            if (!file.exists()) {
                if (!file.mkdirs()) {
                    return null;
                }
            }

//            Toast.makeText(getApplicationContext(), rootDir, Toast.LENGTH_SHORT).show();

            return rootDir;
        } else {
            return null;
        }
    }


    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    public void onClick(View v) {
        if (mVideoRecorder != null) {
            stopScreenRecord();
        } else {
            createScreenCapture();
        }
    }

    private void stopScreenRecord() {
        mVideoRecorder.quit();
        mVideoRecorder = null;
//        if (streamingSender != null) {
//            streamingSender.sendStop();
//            streamingSender.quit();
//            streamingSender = null;
//        }

        mButton.setText("Restart recorder");
    }

    private void createScreenCapture() {
        isRecording = true;
        Intent captureIntent = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            captureIntent = mMediaProjectionManager.createScreenCaptureIntent();
        }
        startActivityForResult(captureIntent, REQUEST_CODE);


        new Thread(new Runnable() {
            @Override
            public void run() {
                startPublishStreamingInternal();
            }
        }).start();
//        mStreamingManager.startConference(Constants.userId, Constants.roomName, Constants.roomToken, new RTCStartConferenceCallback() {
//            @Override
//            public void onStartConferenceSuccess() {
//
//            }
//
//            @Override
//            public void onStartConferenceFailed(int i) {
//
//            }
//        });
//        try {
//            mStreamingProfile.setPublishUrl(pulishString);
//        } catch (URISyntaxException e) {
//            e.printStackTrace();
//        }

//
//        mStreamingManager.setStreamingProfile(mStreamingProfile);

    }

    @Override
    public void notifyStreamStatusChanged(StreamingProfile.StreamStatus streamStatus) {

    }


    @Override
    public boolean onRecordAudioFailedHandled(int i) {
        return false;
    }

    @Override
    public boolean onRestartStreamingHandled(int i) {
        return mStreamingManager.startStreaming();
    }

    @Override
    public Camera.Size onPreviewSizeSelected(List<Camera.Size> list) {
        return null;
    }

    @Override
    public int onPreviewFpsSelected(List<int[]> list) {
        return 0;
    }

    private void setStatusText(final String status) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(ImportStreamingActivity.this, status, Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onStateChanged(StreamingState state, Object o) {
        switch (state) {
            case PREPARING:
                setStatusText(getString(R.string.preparing));
//                new Thread(new Runnable() {
//                    @Override
//                    public void run() {
//                        mStreamingManager.startStreaming();
//                    }
//                }).start();
                Log.e(TAG, "onStateChanged state:" + "preparing");
                break;
            case READY:
                mIsInReadyState = true;
                setStatusText(getString(R.string.ready));
                Log.e(TAG, "onStateChanged state:" + "ready");
                break;
            case CONNECTING:
                Log.e(TAG, "onStateChanged state:" + "connecting");
                break;
            case STREAMING:
                setStatusText(getString(R.string.streaming));
                Log.e(TAG, "onStateChanged state:" + "streaming");
                break;
            case SHUTDOWN:
//                mIsInReadyState = true;
                setStatusText(getString(R.string.ready));
                Log.e(TAG, "onStateChanged state:" + "shutdown");
                break;
            case UNKNOWN:
                Log.e(TAG, "onStateChanged state:" + "unknown");
                break;
            case SENDING_BUFFER_EMPTY:
                Log.e(TAG, "onStateChanged state:" + "sending buffer empty");
                break;
            case SENDING_BUFFER_FULL:
                Log.e(TAG, "onStateChanged state:" + "sending buffer full");
                break;
            case AUDIO_RECORDING_FAIL:
                Log.e(TAG, "onStateChanged state:" + "audio recording failed");
//                showToast(getString(R.string.failed_open_microphone), Toast.LENGTH_SHORT);
//                stopPublishStreaming();
                setStatusText(getString(R.string.failed_open_microphone));
                break;
            case OPEN_CAMERA_FAIL:
                Log.e(TAG, "onStateChanged state:" + "open camera failed");
                setStatusText(getString(R.string.failed_open_camera));
//                showToast(getString(R.string.failed_open_camera), Toast.LENGTH_SHORT);
//                stopPublishStreaming();
                break;
            case IOERROR:
                /**
                 * Network-connection is unavailable when `startStreaming`.
                 * You can do reconnecting or just finish the streaming
                 */
                Log.e(TAG, "onStateChanged state:" + "io error");

                setStatusText(getString(R.string.io_error));
//                showToast(getString(R.string.io_error), Toast.LENGTH_SHORT);
//                sendReconnectMessage();
                // stopPublishStreaming();
                break;
            case DISCONNECTED:
                /**
                 * Network-connection is broken after `startStreaming`.
                 * You can do reconnecting in `onRestartStreamingHandled`
                 */
                Log.e(TAG, "onStateChanged state:" + "disconnected");
                setStatusText(getString(R.string.disconnected));
                // we will process this state in `onRestartStreamingHandled`
                break;
        }
    }

    private boolean startPublishStreamingInternal() {

        String publishAddr = "rtmp://pili-publish.internal-i-focusing.com/com-i-focusing-live-dev/GID_MARSAR_CLOUD_140154302685827072?e=1513668575&token=0xkNXdzEAVclERzD_DBlZknsmJRdJhVeCuDuKPdI:7Q2VLGqNKTYBep1vxAsQ6NQZ7IE=";
//        String publishAddr = StreamUtils.requestPublishAddress(mRoomName);
        if (publishAddr == null) {
//            dismissProgressDialog();
//            showToast("无法获取房间信息/推流地址 !", Toast.LENGTH_SHORT);
            return false;
        }

        try {
            if (StreamUtils.IS_USING_STREAMING_JSON) {
                mStreamingProfile.setStream(new StreamingProfile.Stream(new JSONObject(publishAddr)));
            } else {
                ScreenStreamingManager streamingManager = new ScreenStreamingManager();
                mStreamingProfile.setPublishUrl(publishAddr);
            }
        } catch (JSONException e) {
            e.printStackTrace();
//            dismissProgressDialog();
//            showToast("无效的推流地址 !", Toast.LENGTH_SHORT);
            return false;
        } catch (URISyntaxException e) {
            e.printStackTrace();
//            dismissProgressDialog();
//            showToast("无效的推流地址 !", Toast.LENGTH_SHORT);
            return false;
        }

        mStreamingManager.setStreamingProfile(mStreamingProfile);
        if (!mStreamingManager.startStreaming()) {
            mStreamingManager.startStreaming();
//            dismissProgressDialog();
//            showToast(getString(R.string.failed_to_start_streaming), Toast.LENGTH_SHORT);
            return false;
        }

        ImpDataCollecter impDataCollecter = new ImpDataCollecter();

//        dismissProgressDialog();
//        showToast(getString(R.string.start_streaming), Toast.LENGTH_SHORT);
//        updateControlButtonText();
//        mIsPublishStreamStarted = true;
        /**
         * Because `startPublishStreaming` need a long time in some weak network
         * So we should check if the activity paused.
         */
//        if (mIsActivityPaused) {
//            stopPublishStreaming();
//        }
        return true;
    }
}
